<?php

namespace plugin\coleopenapi\client;

use Exception;
use GuzzleHttp\Client;

class OpenApiClient
{
    protected $guzzleOptions = [
        'verify' => false,
        'timeout' => 30,
    ];
    private $config = [
        'api' => "http://127.0.0.1:8787/openapi",
        'app_key' => "db06c78d1e24cf708a14ce81c9b617ec",
        'app_secret' => "1e24cf708a14ce81",
        'encrypt' => "md5",
    ];

    public function config($config = [])
    {
        if ($config) {
            $this->config = array_merge($this->config, $config);
        }
    }

    public function get($method, $data)
    {
        return $this->request($method, $data, 'GET');
    }

    public function post($method, $data)
    {
        return $this->request($method, $data, 'POST');
    }

    public function request($method, $data, $request_method)
    {
        $this->checkConfig();
        $signData = [
            'appKey' => $this->config['app_key'],
            'timestamp' => time(),
            'noncestr' => self::UUID(),
        ];
        $response = $this->getHttpClient()->request($request_method, $this->config['api'], [
            "headers" => array_merge($signData, [
                'signature' => $this->getSignature(array_merge($signData, $data)),
                'method' => $method,
            ]),
            'json' => $data,
        ])->getBody()->getContents();
        return $response;
    }

    /**
     * @return Client
     */
    public function getHttpClient()
    {
        return new Client($this->guzzleOptions);
    }

    private function getSignature($data)
    {
        //计算签名
        $data = $this->sortData($data);
        $encrypt = $this->config['encrypt'] ?: 'sha256';
        $str = urldecode(http_build_query($data)) . $this->config['app_secret'];
        return hash($encrypt, $str);
    }

    /**
     * 数据排序
     * @param array $data
     * @author mosquito <zwj1206_hi@163.com> 2022-08-25
     */
    private function sortData(array $data)
    {
        $sort = function (array &$data) use (&$sort) {
            ksort($data);
            foreach ($data as &$value) {
                if (is_array($value)) {
                    $sort($value);
                }
            }
        };
        $sort($data);
        return $data;
    }

    static function UUID($prefix = "")
    {
        $chars = md5(uniqid(strval(mt_rand()), true));
        $uuid = substr($chars, 0, 8) . '-'
            . substr($chars, 8, 4) . '-'
            . substr($chars, 12, 4) . '-'
            . substr($chars, 16, 4) . '-'
            . substr($chars, 20, 12);
        return $prefix . strtolower($uuid);
    }

    private function checkConfig()
    {
        if (!$this->config['api']) {
            throw new Exception("配置api不存在");
        }
        if (!$this->config['app_key']) {
            throw new Exception("配置app_key不存在");
        }
        if (!$this->config['app_secret']) {
            throw new Exception("配置app_secret不存在");
        }
        if (!$this->config['encrypt']) {
            throw new Exception("配置encrypt不存在");
        }
    }

    /**
     * @return string[]
     */
    public function getConfig(): array
    {
        return $this->config;
    }
}